Skip to content

feat(sync): add a race-safe outbound controller#137

Open
marcus-pousette wants to merge 1 commit into
cybersemics:fix/auth-outbound-read-guardfrom
marcus-pousette:sync/app-facing-controller
Open

feat(sync): add a race-safe outbound controller#137
marcus-pousette wants to merge 1 commit into
cybersemics:fix/auth-outbound-read-guardfrom
marcus-pousette:sync/app-facing-controller

Conversation

@marcus-pousette

@marcus-pousette marcus-pousette commented May 5, 2026

Copy link
Copy Markdown
Collaborator

What this does

Adds createOutboundSync, an application-facing controller that publishes exact committed local operations through one SyncPeer and one or more outbound transports.

Applications report a local edit once with queueOps(...). The controller deduplicates pending operations by operation ID, wakes low-level live subscriptions, and keeps exact uploads queued until a target is available and online.

Correctness guarantees

  • A timeout aborts the underlying SyncPeer.pushOps; signing or later chunks cannot continue after the controller retries.
  • Replacing or removing targets aborts the active snapshot and replays its operations against the current target set.
  • Concurrent flush() callers share one drain barrier, including work queued during the active run.
  • Repeated attachment of the same target shares one peer attachment with reference-counted, idempotent cleanup.
  • Failed pushes restore the exact batch ahead of newly queued work without creating an unconditional retry loop.
  • Observer exceptions cannot corrupt queue state or create unhandled rejections.
  • close() aborts active work, clears the queue, and prevents late restoration.

Clean integration with #191

This PR is stacked on #191 and preserves its per-exchange Hello correlation, transport-owned state, and exact capability leases. It does not restore the removed global waitForAck/Hello-waiter path or add a compatibility adapter.

Fast paths and limits

  • Empty batches are ignored and duplicate operations coalesce by meta.id.
  • Offline or targetless flushes retain work without network activity or error callbacks.
  • Calls without a timeout or abort signal register no controller cancellation timer.
  • Cancellation cannot retract a frame whose send() already began; later frames and session continuation are stopped, and operation IDs make a late valid frame idempotent.

Size

The cohesive layer is 8 files, +984/-38. Playground adoption, discovery, UI, lockfile churn, and unrelated op-ref behavior remain outside this PR.

Validation

  • sync protocol: 58/58
  • @treecrdt/sync: 32/32
  • outbound controller: 12/12 focused tests
  • TypeScript builds pass

@marcus-pousette marcus-pousette changed the title Add app-facing sync controller Add outbound sync API May 5, 2026
@marcus-pousette marcus-pousette force-pushed the sync/app-facing-controller branch from d7c5bb6 to edcaec2 Compare May 5, 2026 12:07
@marcus-pousette marcus-pousette changed the base branch from runtime-storage-api-cross-tab to main May 5, 2026 12:07
@marcus-pousette marcus-pousette marked this pull request as ready for review May 5, 2026 12:07
@marcus-pousette marcus-pousette marked this pull request as draft June 1, 2026 20:46
@marcus-pousette marcus-pousette marked this pull request as ready for review June 2, 2026 19:20
@marcus-pousette marcus-pousette added enhancement New feature or request area:sync Sync protocol, reconciliation, transport, discovery, and sync servers area:api Public interfaces, bindings, events, and cross-backend contracts labels Jul 12, 2026
@marcus-pousette marcus-pousette force-pushed the sync/app-facing-controller branch from 7821011 to b1b50a2 Compare July 12, 2026 15:23
@marcus-pousette marcus-pousette changed the title Add outbound sync API feat(sync): add a race-safe outbound controller Jul 12, 2026
@marcus-pousette marcus-pousette force-pushed the sync/app-facing-controller branch from b1b50a2 to 46cf7ac Compare July 13, 2026 16:05
@marcus-pousette marcus-pousette changed the base branch from main to fix/auth-outbound-read-guard July 13, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:api Public interfaces, bindings, events, and cross-backend contracts area:sync Sync protocol, reconciliation, transport, discovery, and sync servers enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant